﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MIMSDomain.Abstract;
using MIMSDomain.Entities;
using System.Collections.Generic;
using Moq;
using System.Linq;
using MIMSWeb.Controllers;
using System.Web.Mvc;
using MIMSCore.Abstract;
using MIMSCore.Logging;

namespace MIMSUnitTests.Web.Controllers
{
    [TestClass]
    public class PatientsControllerTests
    {
        public IRepository<Patient> MockPatientsRepository;
        public ILogger<SynkronLogger> logger;

        [TestInitialize]
        public void Initialize(){
            //Arrange
            IList<Patient> patients = new List<Patient>{ 
                new Patient{Id=1,FirstName="John", MiddleName="Adams", LastName="Withaker",Phone="2348036677937"},
                new Patient{Id=2,FirstName="Janet", MiddleName="Adeyemi", LastName="Johnson",Phone="2348057323452"},
                new Patient{Id=3,FirstName="Micheal", MiddleName="Williams", LastName="Smith",Phone="2348098765474"}
            };
            var target = new Mock<IRepository<Patient>>();
            target.Setup(p => p.All).Returns(patients.AsQueryable());
            target.Setup(p => p.GetById(It.IsAny<int>())).Returns((int i) => patients.Where(p => p.Id == i).Single());
            target.Setup(p => p.Save(It.IsAny<Patient>())).Returns((Patient objPatient) =>
            {
                if (objPatient.Id.Equals(default(int)))
                {
                    objPatient.Id = patients.Count() + 1;
                    patients.Add(objPatient);
                }
                else
                {
                    var original = patients.Where(p => p.Id == objPatient.Id).Single();
                    if (original == null)
                    {
                        return false;
                    }
                    //more fields will be added as the patient entity matures.
                    original.Code = objPatient.Code;
                    original.FirstName = objPatient.FirstName;
                    original.MiddleName = objPatient.MiddleName;
                    original.LastName = objPatient.LastName;
                    original.Phone = objPatient.Phone;
                }
                return true;
            });
            target.Setup(p => p.Delete(It.IsAny<Patient>())).Returns((Patient objPatient) =>
            {
                if (patients.Contains(objPatient))
                {
                    patients.Remove(objPatient);
                    return true;
                }
                else
                {
                    return false;
                }
            });

            MockPatientsRepository = target.Object;
            logger = new Mock<ILogger<SynkronLogger>>().Object;
        }

        [TestMethod]
        public void Index()
        {
            //Arrange
            //=> Create an instance of the PatientsController
            PatientsController controller = new PatientsController(MockPatientsRepository, logger);
            //Act
            var expected = (ViewResult)controller.Index();
            
            //Assert
            Assert.IsInstanceOfType(expected.Model, typeof(IQueryable<Patient>));
            //Confirm correct view is returned
            Assert.AreEqual("",expected.ViewName);
            //confirm correct number of patients are returned
            Assert.AreEqual<int>(3, ((IQueryable<Patient>)expected.Model).Count());
        }

        [TestMethod]
        public void AddPatient()
        {
            //Arrange
            PatientsController controller = new PatientsController(MockPatientsRepository, logger);
            var patient = new Patient { FirstName = "Jonathan", MiddleName = "Akinola", LastName = "Babajide", Phone = "2348034046962" };
            int count = MockPatientsRepository.All.Count(); //Before insertion.
            
            //Act
            var expected = (ViewResult)controller.AddPatient(patient);
            //Assert
            Assert.AreEqual(4, MockPatientsRepository.All.Count());
            Assert.AreEqual("", expected.ViewName);
        }

        [TestMethod]
        public void EditPatient()
        {
            //Arrange
            PatientsController controller = new PatientsController(MockPatientsRepository, logger);
            var patient = MockPatientsRepository.GetById(3);
            int count = MockPatientsRepository.All.Count(); //Before insertion.
            patient.FirstName = "Materase";
            //Act
            var actual = (ViewResult)controller.EditPatient(patient);
            //Assert
            Assert.AreEqual("", actual.ViewName);
            Assert.IsNotNull(actual.ViewData.Model);
            Assert.IsInstanceOfType(actual.ViewData.Model, typeof(Patient));
            Assert.AreEqual("Materase", (actual.Model as Patient).FirstName);
        }
        
    }

}
